// ==========================================================================
// GFast自动生成logic操作代码。
// 生成日期：2024-04-24 10:28:10
// 生成路径: internal/app/business/logic/seats.go
// 生成人：周志雄
// desc:座位
// company:云南奇讯科技有限公司
// ==========================================================================

package logic

import (
	"context"
	"fmt"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/tiger1103/gfast/v3/api/v1/business"
	"github.com/tiger1103/gfast/v3/internal/app/business/dao"
	"github.com/tiger1103/gfast/v3/internal/app/business/model"
	"github.com/tiger1103/gfast/v3/internal/app/business/model/do"
	"github.com/tiger1103/gfast/v3/internal/app/business/service"
	"github.com/tiger1103/gfast/v3/internal/app/system/consts"
	"github.com/tiger1103/gfast/v3/library/liberr"
)

func init() {
	service.RegisterSeats(New())
}

func New() *sSeats {
	return &sSeats{}
}

type sSeats struct{}

// 获取某个演出节目的票统计数据
func (s *sSeats) GetSeatsStaticInfo(ctx context.Context, id int) (res []model.SeatsStatusStatic, err error) {
	var seatsList []model.SeatsStatusStatic
	// 执行查询
	err = g.Model("seats").
		Fields("seats.ticket_type AS ticketType, COUNT(seats.id) AS total, SUM(CASE WHEN books.status = 3 THEN 1 ELSE 0 END) AS reserved").
		InnerJoin("books ON books.seat_id = seats.id").
		Where("books.showing_id = ?", id).
		Group("seats.ticket_type").
		Scan(&seatsList)
	if err != nil {
		return nil, err
	}
	g.Model("ticket_remain").Fields("remain_num AS Remaining").Where("performance_id = ?", id).Scan(&seatsList)
	// 返回查询结果
	res = seatsList
	return
}

// 取消订单
func (s *sSeats) Refund(ctx context.Context, req *business.RefundReq) (res *business.RefundRes, err error) {
	g.Dump(req.OrderNum)
	res = new(business.RefundRes)

	err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		// 首先检查订单是否存在且有效
		var order struct {
			OrderId       string `json:"orderId"`
			PerformanceId int    `json:"performanceId"`
			TicketType    string `json:"ticketType"`
			Num           int    `json:"num"`
			TicketStatus  int    `json:"ticketStatus"` // 假设 2 是已购买状态
		}
		err := tx.Model("orders").Fields("order_id AS orderId, performance_id, ticket_type, num, ticket_status").
			Where("order_num = ?", req.OrderNum).Scan(&order)
		g.Dump(order)
		liberr.ErrIsNil(ctx, err, "订单不存在")
		if order.TicketStatus != 2 {
			return fmt.Errorf("该订单已取票或已退票")
		}

		// 更新订单状态为已退票
		_, err = tx.Model("orders").Where("order_id = ?", order.OrderId).
			Data("ticket_status", 3).Update()
		liberr.ErrIsNil(ctx, err, "退票失败")

		// 更新票的剩余数量
		_, err = tx.Model("ticket_remain").Where("performance_id = ? AND ticket_type = ?", order.PerformanceId, order.TicketType).
			Data("remain_num = remain_num + ?", order.Num).Update()
		liberr.ErrIsNil(ctx, err, "退单后新增票数量失败")
		return nil
	})
	return
}

// 座位设置列表
func (s *sSeats) SeatsSetting(ctx context.Context, req *business.SeatsSettingReq) (res *business.SeatsSettingRes, err error) {
	res = new(business.SeatsSettingRes)
	model := g.Model("orders")
	// 演出场次
	if req.PerformanceDate != nil && req.PerformanceTime != "" {
		model.Where("performances.performance_date", req.PerformanceDate).Where("performances.performance_time", req.PerformanceTime)
	}
	// 代理商
	if req.AgentName != "" {
		model.Where("agents.name like ?", "%"+req.AgentName+"%")
	}
	// 姓名
	if req.Name != "" {
		model.Where("name like ?", "%"+req.Name+"%")
	}
	// 手机号
	if req.Phone != "" {
		model.Where("phone like ?", "%"+req.Phone+"%")
	}
	err = model.Fields("orders.*, performances.performance_date AS performanceDate,performances.performance_time AS performanceTime,agents.name as agentName,venues.venue_name as venueName,performances.id as performanceId,performances.performance_name as performanceName").
		// 关联节目
		InnerJoin("performances on performances.id = orders.performance_id").
		// 关联场馆
		InnerJoin("venues on venues.id = performances.venue_id").
		// 关联代理商
		InnerJoin("agents on agents.id = orders.agent_id").
		Scan(&res.List)
	res.Total = len(res.List)
	return
}

func (s *sSeats) List(ctx context.Context, req *business.SeatsSearchReq) (listRes *business.SeatsSearchRes, err error) {
	listRes = new(business.SeatsSearchRes)
	err = g.Try(ctx, func(ctx context.Context) {
		m := dao.Seats.Ctx(ctx).WithAll()
		if req.Id != "" {
			m = m.Where(dao.Seats.Columns().Id+" = ?", req.Id)
		}
		if req.RowNumber != "" {
			m = m.Where(dao.Seats.Columns().RowNumber+" = ?", gconv.Int(req.RowNumber))
		}
		if req.SeatNumber != "" {
			m = m.Where(dao.Seats.Columns().SeatNumber+" = ?", gconv.Int(req.SeatNumber))
		}
		if req.TicketType != "" {
			m = m.Where(dao.Seats.Columns().TicketType+" = ?", gconv.Int(req.TicketType))
		}
		if req.VenueId != "" {
			m = m.Where(dao.Seats.Columns().VenueId+" = ?", gconv.Int(req.VenueId))
		}
		if len(req.DateRange) != 0 {
			m = m.Where(dao.Seats.Columns().CreatedAt+" >=? AND "+dao.Seats.Columns().CreatedAt+" <=?", req.DateRange[0], req.DateRange[1])
		}
		if req.PageNum == 0 {
			req.PageNum = 1
		}
		listRes.CurrentPage = req.PageNum
		if req.PageSize == 0 {
			req.PageSize = consts.PageSize
		}
		order := "id asc"
		if req.OrderBy != "" {
			order = req.OrderBy
		}
		var res []*model.SeatsInfoResVo
		err = m.Fields("seats.*, venues.venue_name AS venueName").
			InnerJoin("venues on venues.id = seats.venue_id").Page(req.PageNum, req.PageSize).Order(order).Scan(&res)
		liberr.ErrIsNil(ctx, err, "获取数据失败")
		listRes.List = make([]*model.SeatsListResVo, len(res))
		for k, v := range res {
			listRes.List[k] = &model.SeatsListResVo{
				Id:         v.Id,
				RowNumber:  v.RowNumber,
				SeatNumber: v.SeatNumber,
				TicketType: v.TicketType,
				VenueId:    v.VenueId,
				VenueName:  v.VenueName,
				CreatedAt:  v.CreatedAt,
			}
		}

		listRes.Total = len(listRes.List)
		liberr.ErrIsNil(ctx, err, "获取总行数失败")
	})
	return
}

func (s *sSeats) GetById(ctx context.Context, id int) (res *model.SeatsInfoRes, err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		err = dao.Seats.Ctx(ctx).WithAll().Where(dao.Seats.Columns().Id, id).Scan(&res)
		liberr.ErrIsNil(ctx, err, "获取信息失败")
	})
	return
}

func (s *sSeats) Add(ctx context.Context, req *business.SeatsAddReq) (err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		_, err = dao.Seats.Ctx(ctx).Insert(do.Seats{
			Id:         req.Id,
			RowNumber:  req.RowNumber,
			SeatNumber: req.SeatNumber,
			TicketType: req.TicketType,
			VenueId:    req.VenueId,
		})
		liberr.ErrIsNil(ctx, err, "添加失败")
	})
	return
}

func (s *sSeats) Edit(ctx context.Context, req *business.SeatsEditReq) (err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		_, err = dao.Seats.Ctx(ctx).WherePri(req.Id).Update(do.Seats{
			RowNumber:  req.RowNumber,
			SeatNumber: req.SeatNumber,
			TicketType: req.TicketType,
			VenueId:    req.VenueId,
		})
		liberr.ErrIsNil(ctx, err, "修改失败")
	})
	return
}

func (s *sSeats) Delete(ctx context.Context, ids []int) (err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		_, err = dao.Seats.Ctx(ctx).Delete(dao.Seats.Columns().Id+" in (?)", ids)
		liberr.ErrIsNil(ctx, err, "删除失败")
	})
	return
}
